package com.howso.cloud.common.crypto;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * 数据加密
 */
@Slf4j
public class DataCryptoUtil {
    private static String AES_GCM_2128_ALGORITHM = "data.algorithm.padding";
    private static final String AES_KEY_ALGORITHM = "data.algorithm.name";
    private static final int AES_KEYSIZE = 128;
    
    private static final  String ALGORITHM;
    private static final  String KEY_ALGORITHM;
    static {
        ALGORITHM=SettingUtils.get(AES_GCM_2128_ALGORITHM);
        KEY_ALGORITHM=SettingUtils.get(AES_KEY_ALGORITHM);
    }
    protected static String decrypt(String content, String keyStr) {
        try {
            if (StringUtils.isEmpty(content) || StringUtils.isEmpty(keyStr)) {
                throw new Exception("AESGCM256解密异常,检查文本或密钥");
            }
            //Cipher cipher = Cipher.getInstance(gcm256algorithm);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(keyStr), KEY_ALGORITHM);
            
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] message = Base64.getDecoder().decode(content);
            if (message.length < 12 + 16) throw new IllegalArgumentException();
            GCMParameterSpec params = new GCMParameterSpec(AES_KEYSIZE, message, 0, 12);
            cipher.init(Cipher.DECRYPT_MODE, key, params);
            byte[] decryptData = cipher.doFinal(message, 12, message.length - 12);
            String decript = new String(decryptData);
            log.info("content:{}, after decrypt:{}",content,decript);
            return decript;
        } catch (Exception e) {
            log.error("AESGCM256解密文本处理失败,error:{}", e);
        }
        return null;
    }
    protected static String encrypt(String content, String keyStr) {
        try {
            if (StringUtils.isEmpty(content) || StringUtils.isEmpty(keyStr)) {
                throw new Exception("AESGCM256加密异常,检查文本或密钥");
            }
            
            SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(keyStr), KEY_ALGORITHM);

            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] iv = cipher.getIV();
            assert iv.length == 12;
            byte[] encryptData = cipher.doFinal(content.getBytes());
            assert encryptData.length == content.getBytes().length + 16;
            byte[] message = new byte[12 + content.getBytes().length + 16];
            System.arraycopy(iv, 0, message, 0, 12);
            System.arraycopy(encryptData, 0, message, 12, encryptData.length);
            return Base64.getEncoder().encodeToString(message);
        } catch (Exception e) {
            log.error("AESGCM256加密文本处理失败,error:{}", e);
        }
        return null;
        
    }
    /**
     * 生成AES密钥
     * @return
     */
    protected static String generateAESKey(){
        KeyGenerator generator = null;
        try {
            generator = KeyGenerator.getInstance(KEY_ALGORITHM);
            //初始化密钥生成器，AES要求密钥长度为128位、192位、256位
            generator.init(AES_KEYSIZE);
            SecretKey secretKey = generator.generateKey();
            return Base64.getEncoder().encodeToString(secretKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            log.error("密钥生成异常,error:", e);
        }
        return "";
    }
    
}